package entity;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import db.Manager;

/**
 * @author frankcarnevale
 *
 */
public class System {
	final String adminName = "admin";
	final String adminPassword = "pass";
	String adminKey;
	static System system = null;
	
	/**
	 * Returns the single instance of the System class
	 * @return
	 */
	public static System getInstance(){
		if(system == null)
			system = new System();
		return system;
	}
	
	private System(){
		if(!Manager.connect()){
			throw new RuntimeException("Failed to connect to database");
		}
	}
	
	/**
	 * Returns the stored event with the given id, or null if no event with that ID exists
	 * @param eventId
	 * @return
	 */
	public DecisionLinesEvent getEvent(String eventId){
		return Manager.retrieveEvent(eventId);
	}
	
	/**
	 * Returns an List of DecisionLinesEvents of the given type ('open' or 'closed').
	 * 
	 * @param type The event type ('open' or 'closed')
	 * @return All DecisionLinesEvents of the given type
	 */
	public List<DecisionLinesEvent> getEvents(String type) {
		return Manager.retrieveEventsByType(type);
	}
	
	/**
	 * Creates an open event with the given parameters, returns the unique String id of the created event
	 * @param question
	 * @param eventType
	 * @param turnType
	 * @param numberOfChoice
	 * @param numberOfEdge
	 * @param phase
	 * @param users
	 * @return
	 */
	public String createOpenEvent(String question, String eventType, String turnType, int numberOfChoice, int numberOfEdge, String phase, ArrayList<User> users){
		String eventId = UUID.randomUUID().toString();
		Manager.insertEvent(eventId, question, eventType, turnType, numberOfChoice, numberOfEdge, phase, users, null);
		return eventId;
	}
	
	/**
	 * Creates an closed event with the given choices, returns unique String id for the event
	 * @param question
	 * @param eventType
	 * @param turnType
	 * @param numberOfChoice
	 * @param numberOfEdge
	 * @param phase
	 * @param users
	 * @param choices
	 * @return
	 */
	public String createClosedEvent(String question, String eventType, String turnType, int numberOfChoice, int numberOfEdge, String phase, ArrayList<User> users, ArrayList<String> choices){
		String eventId = UUID.randomUUID().toString();
		ArrayList<Line> lines = new ArrayList<Line>(choices.size());
		for(int i=0;i<choices.size();i++){
			lines.add(i,new Line(choices.get(i),i));
		}
		Manager.insertEvent(eventId, question, eventType, turnType, numberOfChoice, numberOfEdge, phase, users, lines);
		return eventId;
	}
	

	/**
	 * Updates the given event in the database
	 * @param id
	 * @param event
	 */
	public void updateEvent(String id, DecisionLinesEvent event){
		Manager.updateEvent(id, event);
	}
	
	/**
	 * Deletes the event in the database with the given id, if it exists.
	 * 
	 * @param id
	 * @return true if the event is deleted successfully, false otherwise.
	 */
	public boolean deleteEventById(String id){
		return Manager.deleteEvent(id);
	}
	
	// TODO
	public int deleteEventByCriteria(boolean completed, Date olderThan){
		return Manager.deleteEventByCriteria(completed, olderThan);
	}

	public boolean validateAdmin(String adminName, String adminPassword){
		return this.adminName.equals(adminName) && this.adminPassword.equals(adminPassword);
	}
	
	/**
	 * Determines whether the passed in admin key is valid
	 * 
	 * @param adminKey
	 * @return
	 */
	public boolean validateAdminKey(String adminKey) {
		return this.adminKey.equals(adminKey);
	}
	
	/**
	 * Generates and returns a new admin key
	 * 
	 * @return
	 */
	public String generateNewAdminKey() {
		this.adminKey = UUID.randomUUID().toString();
		return this.adminKey;
	}
}
